1 Introduction

1.1 C’est quoi R ?

  • R est un langage dérivé du langage S, interprété (en opposition aux langages compilés), non typé.
  • R est un logiciel libre (sous licence GNU GPL), gratuit, multiplateforme.
  • R est orienté vers l’analyse statistique (calculs et graphiques).

  • Le projet R naît en 1993, se structure en 1997 et la version 1.0.0 est publiée en 2000.
  • La R Core Team est un groupe d’une vingtaine de personnes au cœur du développement du langage R.
  • R est essentiellement codé en C, R et Fortran.

  • De très nombreux.ses utilisateur.trices à travers le monde.
  • Utilisé dans un grand nombre de disciplines.
  • Un large essor dans le monde académique mais aussi dans les entreprises privées.
  • Conférences annuelles :
    • UseR, la prochaine à Saint-Louis, aux Etats-Unis, du 7 au 10 juillet 2020.
    • Rencontres R, la prochaine à Paris, du 15 au 17 juillet 2020.
  • Le R Journal paraît deux fois par an, les articles sont en accès libre et soumis à un comité de lecture.

1.2 C’est quoi un package (library) R ?

  • Un package est l’unité fondamentale de code partageable dans R.
  • Un package contient du code et/ou des données, de la documentation, des tests.
  • 30 packages recommandés sont automatiquement distribués lors de l’installation de R.
  • Le dépôt officiel de packages R est le CRAN (The Comprehensive R Archive Network).
  • Presque 15000 packages existent sur CRAN (septembre 2019).


Evolution du nombre de packages depuis 1998 (LLC 1999)


  • Le dépôt CRAN de packages est déployé à travers le monde via les miroirs locaux.
  • Le miroir CRAN de Lyon 1 est physiquement situé au LBBE : https://pbil.univ-lyon1.fr/CRAN/
  • Bioconductor est un autre dépôt officiel de packages R dédiés aux problématiques bioinformatiques.

  • Tout le monde peut proposer un nouveau package pour valoriser et partager ses méthodes, ses codes, ses données.
  • Un ensemble de contraintes pour créer et soumettre son propre package (R Core Team 2018b ; Wickham 2015b) qui facilitent largement l’installation et l’exploration de nouveaux packages, accessibles en open-source, par les utilisateur.trices.

  • install.packages("nomPkg") : installe le package nomPkg localement sur ma machine.
  • library(nomPkg) : charge le package nomPkg dans ma session R ; cette commande doit être exécutée à chaque nouvelle session, sauf si vous avez sauvegardé votre session.

# installation du package 'ggplot2' sur ma machine
install.packages("ggplot2", repos = "https://pbil.univ-lyon1.fr/CRAN/")
# chargement du package 'ggplot2' dans ma session R en cours
library(ggplot2)


1.3 Bien citer R

  • citation() : retourne la manière de citer R dans les publications.
  • citation("nomPkg") : retourne la manière de citer le package nomPkg dans les publications.
# référence bibliographique pour citer le logiciel R
citation()
## 
## To cite R in publications use:
## 
##   R Core Team (2019). R: A language and environment for
##   statistical computing. R Foundation for Statistical Computing,
##   Vienna, Austria. URL https://www.R-project.org/.
## 
## A BibTeX entry for LaTeX users is
## 
##   @Manual{,
##     title = {R: A Language and Environment for Statistical Computing},
##     author = {{R Core Team}},
##     organization = {R Foundation for Statistical Computing},
##     address = {Vienna, Austria},
##     year = {2019},
##     url = {https://www.R-project.org/},
##   }
## 
## We have invested a lot of time and effort in creating R, please
## cite it when using it for data analysis. See also
## 'citation("pkgname")' for citing R packages.

# référence bibliographique pour citer le package 'ggplot2'
citation("ggplot2")
## 
## To cite ggplot2 in publications, please use:
## 
##   H. Wickham. ggplot2: Elegant Graphics for Data Analysis.
##   Springer-Verlag New York, 2016.
## 
## A BibTeX entry for LaTeX users is
## 
##   @Book{,
##     author = {Hadley Wickham},
##     title = {ggplot2: Elegant Graphics for Data Analysis},
##     publisher = {Springer-Verlag New York},
##     year = {2016},
##     isbn = {978-3-319-24277-4},
##     url = {https://ggplot2.tidyverse.org},
##   }


1.4 Fichiers et répertoire de travail

  • Une session R est définie par l’environnement global en cours, dans lequel se trouvent des packages, fonctions, données, variables importées ou créées.
  • Une session R peut être sauvegardée pour être chargée plus tard ou ailleurs :
    • l’environnement est sauvegardée dans un fichier qui se nomme .RData,
    • l’historique des commandes utilisées dans la session est sauvegardée dans un fichier qui se nomme .Rhistory.
  • De manière pratique, on travaille, d’un côté avec un éditeur dans lequel on peut modifier son script (un fichier avec une extension .R qui permet d’enregistrer les étapes qui ont permis de créer les objets R) et d’un autre côté, une invite de commande dans laquelle on accède à sa session R.

  • getwd() : retourne le chemin du répertoire courant de travail.
  • setwd() : définit le répertoire de travail.
  • .libPaths() : retourne le nom des tous les répertoires contenant les packages R installés sur votre machine.
  • sessionInfo() : retourne des informations sur la session R en cours.


A VOUS ! (avec des commandes R)

  • 1.4.A - Quel est votre répertoire courant de travail ?
  • 1.4.B - Dans combien de répertoires les packages R de votre machine sont localisés ?
  • 1.4.C - Quelle est la version de R utilisée par votre session ?


1.5 Support et aide

  • Le nom du logiciel ne facilite pas les recherches sur le web.
  • Mais la communauté des utilisateur.trices est mature et très active.
  • Beaucoup de supports de formation, de documents disponibles, de forums, …

La documentation officielle de R

Se documenter dans R

Si vous connaissez le nom de ce que vous cherchez (package, fonction, jeu de données) :

  • ?nomFctn ou help("nomFctn") : retourne la fiche d’aide de la fonction nomFctn.
  • example(nomFctn) : exécute l’exemple associé à la fonction nomFctn.
  • vignette(package = "nomPkg") : charge la vignette du package nomPkg, un guide d’utilisation plus complet du package.

D’autres documentations utiles

# documentation sur le package 'ggplot2'
help("ggplot2-package")

# documentation sur la fonction 'geom_histogram' (package 'ggplot2')
?geom_histogram
help("geom_histogram")
help("geom_histogram", package = "ggplot2") # s'il y a une ambigüité sur la provenance de la fonction

# vignettes du package 'ggplot2'
vignette(package = "ggplot2")
vignette("ggplot2-specs", package = "ggplot2") # quand il y a plusieurs vignettes dans le package


2 Les bases du langage R

  • R est sensible à la casse (majuscule / minuscule).
  • Les commentaires sont précédés du signe #.
  • Pas de ; à la fin des lignes de commande (comme c’est le cas dans d’autres langages).
  • R gère les décimales avec un point (pas une virgule).
  • Le symbole <- permet d’affecter une valeur (élément de droite) à une variable (élément de gauche).

2.1 Les données

2.1.1 Importer et exporter des données

Importer des données

  • read.table() : importe un fichier de données tabulées.
  • scan(), readline() et readLines() : importent des données de manière plus flexible (format des données, options d’import, saisie interactive).
  • data() et load() : importent des jeux de données (généralement au format .RData ou .rda).

D’autres packages pour lire des données :

  • readr (Wickham, Hester, and Francois 2018) pour accèder aux fichiers plats de manière performante
  • readxl (Wickham and Bryan 2019) et XLConnect (GmbH et al. 2018) pour traiter les fichiers Excel
  • foreign (R Core Team 2017) (installé automatiquement avec R) pour lire et écrire des données issus de logiciels tels que SPSS, SAS, Stata, …
  • seqinR (Charif and Lobry 2007) et sa fonction read.fasta pour faciliter l’import de données génomiques
  • rjson (Couture-Beil 2018) pour traiter les fichiers JSON
  • XML (Lang and CRAN Team 2019) pour accèder à des données issues du web
  • bigmemory (Kane, Emerson, and Weston 2013) et ff (Adler et al. 2018) pour les données volumineuses

Quand R charge un jeu de données, toutes les données sont chargées et sont donc disponibles dans la mémoire :

  • ce qui permet de bonnes performances de calcul,
  • ce qui peut être problématique quand le volume des données est important.
# chargement du jeu de données 'doubs' du package 'ade4'
install.packages("ade4")
library(ade4)
data(doubs)


Exporter et sauver des données

Exporter des données a un intérêt (1) quand les données initialement importées ont été modifiées dans R, ou (2) quand les données ont été générées/simulées dans R.

  • save() : sauvegarde un ensemble d’objets R dans un fichier spécifique (généralement au format .RData ou .rda).
  • write.table : enregistre des données tabulées dans un fichier.

2.1.2 Les types de données

Ici, sont présentés les principaux types de données. Il existe d’autres types de données (dates, séries temporelles, données spatiales, …) et les possibilités de typage sont enrichies par de nouveaux packages.

Les données numériques

  • numeric, double, integer
  • is.numeric(), is.double(), is.integer() : testent si un objet est numérique.
  • as.numeric(), as.double(), as.integer() : convertissent un objet en numérique.

Les facteurs

Un facteur est une variable catégorielle qui possède un attribut levels définissant l’ensemble des valeurs qu’il peut prendre.

  • factor
  • is.factor() : teste si un objet un facteur.
  • as.factor() : convertit un objet en facteur.
  • levels() : retourne ou affecte les niveaux de valeur d’un facteur.

Lors de l’import de données, il faut rester vigilent sur le typage automatique des données, notamment pour les facteurs. Par exemple, une variable prenant les valeurs 1 et 2 pour le sexe des individus, pourrait automatiquement être définie comme numérique lors de son import dans R et devra donc être convertie en facteur pour être traitée correctement.

Les caractères

  • character
  • is.character() : teste si un objet est un caratère.
  • as.character() : convertit un objet en caractère.
  • paste() : concatène deux chaînes de caractères.
  • letters, LETTERS, month.abb, month.name : retournent des chaînes de caractères prédéfinies.

Les valeurs booléennes

  • TRUE et FALSE
  • is.logical() : teste si un objet est booléen.
  • as.logical() : convertit un objet en booléen.
  • isTRUE() : teste si une valeur est égale à TRUE.
  • ! (négation logique), & (‘et’ logique), | (‘ou’ logique)

Les valeurs manquantes

  • NA (i.e. Not Available) est un indicateur de valeur manquante. is.na() teste si une valeur est manquante.
  • NaN (i.e. Not a Number) matérialise une valeur numérique qui n’est pas réelle. is.nan() teste si un numérique n’est pas réel.
  • NULL représente un objet vide. is.null() teste si une valeur est définie. NULL est différent de NA.

2.1.3 Les structures de données

Quelques commandes utiles

  • str() : retourne la structure d’un objet R.
  • class() et typeof() : retournent la classe (au sens POO) et le type d’un objet (au sens type de R). La classe d’un objet peut être définie/modifiée par l’utilisateur.trice, pas son type. Les deux fonctions peuvent renvoyer le même résultat.
  • names(), colnames() et rownames() : retournent, s’ils existent, les noms d’un objet, le nom des colonnes et des lignes d’un objet.
  • length() et dim() : retournent la longueur et la dimension d’un objet.
  • head() et tail() : extraient les premiers et les derniers éléments d’un objet.
  • [, [[ et $ : extraient, dans la mesure du possible, un ou plusieurs éléments d’un objet.

L’extraction d’un élément d’un objet peut se faire en spécifiant :

  • un entier positif, pour sélectionner les éléments situés à une position spécifique
  • un entier négatif, pour supprimer les éléments situés à une position spécifique
  • un booléen, pour sélectionner les éléments pour lesquels la valeur est TRUE
  • une chaîne de caractère, pour sélectionner les éléments dont le nom correspond

A noter : l’indexation des objets commence à 1 (et non à 0, comme dans certains langages).

Les vecteurs

  • Le vecteur est la structure de base des objets dans R.
  • Un vecteur rassemble nécessairement des données de type homogène.
  • vector() : crée un vecteur.
  • is.vector() : teste si un objet est un vecteur.
  • as.vector() : convertit un objet en vecteur.
  • seq(), c(), rep(), : : générent quelques vecteurs utiles.

Les matrices

  • Une matrice rassemble nécessairement des données de type homogène.
  • matrix() : crée une matrice.
  • is.matrix() : teste si un objet est une matrice.
  • as.matrix() : convertit un objet en matrice.
  • cbind() et rbind() : combinent des matrices en colonne et en ligne.
  • nrow() et ncol() : retournent le nombre de lignes et de colonnes d’une matrice.

Les data frames

  • Le data.frame est une structure spécifique à R.
  • Un data frame est un tableau à deux dimensions, dans lequel les colonnes peuvent avoir des types hétérogènes.
  • data.frame() : crée un data frame.
  • is.data.frame() : teste si un objet est un data frame.
  • as.data.frame() : convertit un objet en data frame
  • colnames() et rownames() : retournent le nom des lignes et des colonnes d’un data frame.

Les listes

  • Une liste peut contenir des données de type et de structure hétérogènes.
  • list() : crée une liste.
  • is.list() : teste si un objet est une liste.
  • as.list() : convertit un objet en liste.
  • unlist() : simplifie une liste en vecteur ( comportement à surveiller).
# structure des données 'doubs'
str(doubs)
is.list(doubs)

# nom des objets contenus dans 'doubs'
names(doubs)

# dimension de l'objet 'fish' de 'doubs'
dim(doubs$fish)

# les 10 premières lignes de 'fish'
head(doubs$fish, 10)
doubs[["fish"]][1:10, ]

# création d'un objet 'dfish'
dfish <- doubs$fish

# nom des colonnes de 'dfish'
names(dfish)
colnames(dfish)

# dimension de 'dfish'
dim(dfish)

# l'objet 'dfish' est-il un data.frame ?
is.data.frame(dfish)

# classe de la colonne 'Cogo' de 'dfish'
class(dfish$Cogo)

# type de la colonne 'Satr' de 'dfish'
typeof(dfish$Satr)

# modification de la classe de la colonne 'Cogo' de 'dfish'
class(dfish$Cogo) <- "character"

# structure de 'dfish'
str(dfish)

# modification du type de la colonne 'Satr' de 'dfish'
# renvoie une erreur : impossible de modifier le 'type' d'une variable
# typeof(dfish$Satr) <- "character"


2.1.4 Manipuler les données

  • pour nettoyer les données brutes qui viennent d’être importées
  • plutôt depuis une session R que directement dans le fichier des données brutes
  • en gardant une trace des étapes de transformation dans un script R pour pouvoir les reproduire éventuellement
  • pour rendre les données exploitables au sens d’une analyse statistique
  • trier, sélectionner, couper, jointer, …

Quelques outils pour le ménage et le rangement

  • sort() , order() et rank() : trient et ordonnent un vecteur.
  • sample() : échantillonne un nombre d’éléments, avec ou sans remise.
  • table() : construit une table de contingence.
  • which() : retourne les positions des éléments pour lesquels la condition est vraie.
  • na.omit() : supprime les valeurs NA d’un objet.

  • subset() : sélectionne un sous-ensemble de données.
  • %in% et match() : retournent les positions des éléments d’un premier objet qui correspondent avec un deuxième.
  • cut() : coupe un vecteur en plusieurs sections et le convertit en facteur.
  • with() : évalue une expression dans un environnement de données.
  • na.fail(), na.exclude(), na.pass() : traitent les NA.

Des spécialistes de la grammaire des données

  • Le package plyr(Wickham 2011) : arrange(), mutate(), summarise(), join(), …
  • Le package dplyr (Wickham et al. 2017) : filter(), arrange(), select(), rename(), mutate(), transmute(), summarise(), …
  • Le package stringr (Wickham 2018)
  • Le package tidyr (Wickham and Henry 2018)
  • Le package magrittr (Bache and Wickham 2014)
  • Le package stringi (Gagolewski 2017)


AVANT DE COMMENCER : Prenez connaissance, en Annexe, de la documentation liée aux jeux de données que vous allez étudier sur les varis dans la suite de ce cours.


A VOUS ! (avec des commandes R)

  • 2.1.A - Chargez le jeu de données dfvaris_litter.Rdata dans votre session R.
  • 2.1.B - Quelle est la structure de ce jeu de données (dimension, nombre de portées, nom des variables, type de variables, données manquantes, …) ?
  • 2.1.C - Combien d’espèces sont présentes dans ce jeu de données ? Et combien y a-t-il de portées suivies par espèce ?
  • 2.1.D - Créez un nouveau jeu de données sub_dfvaris_litter contenant 100 portées (prises au hasard) de chaque espèce.
  • 2.1.E - Ajoutez une nouvelle variable PAD (Parental Age Difference) dans dfvaris_litter, égale à l’âge du père moins l’âge de la mère.


2.2 Eléments de programmation

2.2.1 Les structures de contrôle

Les structures conditionnelles : if, else, ifelse et switch

  • if(test)
  • if(test) expr.oui else expr.non
  • ifelse(test, oui, non). Les objets en sortie doivent avoir la même taille et la même structure que l’objet en entrée. Cette fonction est donc facilement source d’erreur, en plus d’être identifiée comme assez lente.
  • switch(var, val1 = expr.val1, val2 = expr.val2, val3 = expr.val3, ...)

Les structures itératives : for, while et repeat

  • for(var in seq) expr
  • while(test) expr. L’expression continue à être exécutée tant qu’une condition est respectée.
  • repeat expr
  • break interrompt une boucle ; next passe à l’itération suivante.
  • La boucle for incrémente elle-même l’itérateur.
  • Pour while et repeat, il est primordial d’incrémenter explicitement l’itérateur, sans quoi, le code pourrait boucler à l’infini et endommager un programme.

2.2.2 Les fonctions

Utiliser une fonction existante

  • Plusieurs dizaines de fonctions ont déjà été utilisées depuis le début de ce document (install.packages(), library(), read.table(), data(), is.numeric(), as.numeric(), …).
  • args(), formals() et formalArgs() donnent, sous différentes formes, les éléments qui caractérisent une fonction.
  • Quand une fonction est appelée, il n’est pas impératif de spécifier le nom des arguments auxquels sont données des valeurs, à condition qu’il n’y ait pas d’ambiguïté entre les différents paramètres. Cependant, pour une meilleure lisibilité et une meilleure performance, il est recommandé d’expliciter le nom des arguments auxquels des valeurs sont données.
  • ls() liste l’ensemble des objets créés par l’utilisateur.trice dans un environnement R.
ls()
args(ls)
args("plot")
args("plot.default")
str(plot.default)


Créer sa propre fonction

  • Il est bien sûr possible de créer sa propre fonction.
  • Une valeur par défaut peut être définie pour un ou tous les arguments d’une fonction. Déterminer des valeurs par défaut peut faciliter l’usage d’une fonction.
  • Plus l’indentation du corps de la fonction sera soignée, plus la fonction sera lisible, compréhensible, donc facilement utilisable.
  • Par construction, il n’y a pas de contrôle sur le typage des objets dans R. Introduire des contrôles dans le corps de sa fonction est un bon réflexe pour se prémunir d’erreurs typiques et pour orienter l’utilisateur.trice.

  • return() : matérialise les éléments renvoyés par la fonction créée.
  • invisible() : retourne une copie (temporairement) invisible d’un objet.
  • on.exit() : stocke des valeurs d’éléments qui seront restaurées à la fin/sortie de la fonction.
  • stop(), stopifnot(), message() et error() : caractérisent les messages envoyés à l’utilisateur.trice au cours de l’exécution d’une fonction.


A VOUS ! (avec des commandes R)

Supposez une fonction info_vect qui prend en entrée un vecteur et qui renvoie une liste contenant la classe de ce vecteur, sa longueur, le résultat de la fonction summary appliquée à ce vecteur et le nombre de valeurs manquantes contenues dans ce vecteur.

  • 2.2.A - Avant même de créer cette fonction, pouvez-vous dire quelle est la taille de l’objet qu’elle retourne ?
  • 2.2.B - Créez cette fonction.
  • 2.2.C - Appliquez cette fonction à la variable survlitter48h du jeu de données dfvaris_litter.
  • 2.2.D - Faire une boucle pour appliquer cette fonction à chaque variable du jeu de données dfvaris_litter.
  • 2.2.E - Remplacez la boucle développée dans la question 2.2.E par une fonction lapply pour obtenir le même résultat.
  • 2.2.F - Laquelle des deux méthodes (2.2.E vs 2.2.F) est la plus rapide à l’exécution ?


3 Les graphiques dans R


  • Lisibilité : l’objectif est de communiquer un message scientifique clair.
  • Reproductibilité : le graphique est construit par un script R (ne pas bricoler un graphique via un logiciel de dessin).
  • Honnêteté et objectivité : ne pas distordre le graphique pour biaiser l’analyse des données.


Quelques exemples de mauvaises représentations graphiques


Ex1
Ex2
Ex3

3.1 Réfléchir sa représentation graphique

Un graphique scientifique

  • Un graphique n’est pas une oeuvre d’art.
  • Définir le message scientifique que vous souhaitez communiquer.
  • Ne pas surcharger : un seul message par graphique ; éviter les distractions visuelles (trop de couleurs, trop d’étiquettes, fond trop présent, …).
  • La visualisation des données en deux parties : l’exploration des données (la construction des graphiques doit être rapide et efficace, l’apparence du graphique est secondaire) et la présentation des données (les graphiques doivent être de haute qualité, reproductibles).

Le choix du graphique

  • Adapter le type de graphique aux données représentées (source : https://www.data-to-viz.com/).
  • Adapter le type de graphique au média de communication utilisé (temps d’exposition).
  • Eviter les graphiques circulaires ou en 3D : l’oeil humain sait mal comparer les surfaces.

Annoter judicieusement son graphique

  • Ajouter un titre global, des noms aux axes : ni trop court, ni trop long.
  • Ajouter une légende si nécessaire ou, si possible, s’en passer pour alléger le graphique.
  • Attirer l’attention sur un élément particulier en intégrant des éléments graphiques (texte, couleur).
  • Inclure une expression mathématique avec expression().

Travailler les couleurs

  • L’information apportée par les couleurs doit avoir un sens.
  • Tenir compte des défauts visuels de vos potentiel.les lecteur.trices.
  • Package grDevices (R Core Team 2018a) : colors(), palette(), rainbow() et grey().
  • Package RColorBrewer (Neuwirth 2014) : brewer.pal() et display.brewer.all() (pour connaître les palettes disponibles).
  • Packages wesanderson, ggsci, ggthemes, colourpicker (addin RStudio), …


A VOUS ! (avec des commandes R)

  • 3.1.A - A l’aide du package graphics, inspirez-vous de la Figure S1 (ci-dessous) en annexe de l’article de Tidière et al. (2018) pour créer un graphique contenant :
    • l’âge de la mère en fonction de l’âge du père de chaque portée, en différenciant les deux espèces
    • la droite de régression du modèle linéaire expliquant l’âge du père par l’âge de la mère
    • l’équation de cette droite de régression
    • la droite représentant un modèle d’accouplement des varis où l’âge du père est égal à l’âge de la mère
    • des points supplémentaires représentant l’âge moyen du père pour chaque âge de la mère, en différenciant les deux espèces
  • 3.1.B - Pour quelles raisons le graphique produit à la question 3.1.A est légèrement différent de celui publié dans l’article de Tidière et al. (2018) ?
  • 3.1.C - Proposez des améliorations au graphique qui a été publié.



3.2 Des graphiques pour l’analyse statistique

Les graphiques font partie intégrante de l’analyse statistique des données.

Dans le package graphics (dans la base de R, R Core Team (2018a)) :

  • Fonction centrale et générique pour représenter des données : plot.
  • Fonctions graphiques de haut niveau : boxplot(), hist(), image(), contour(), dotchart(), curve(), barplot(), stripchart(), pie(), stars(), matplot(), pairs(), mosaicplot(), smoothScatter(), …
  • Certaines fonctions de haut niveau renvoient les éléments statistiques qui ont permis de construire le graphique : hist(), boxplot(), barplot().
  • Fonctions graphiques de bas niveau (i.e. utilisables uniquement si une fonction graphique de haut niveau a été appelée auparavant) : points(), lines(), segments(), text(), abline(), legend(), title(), mtext(), rect(), arrows(), polygon(), grid(), rug(), …
  • Graphiques quantile-quantile : qqnorm, qqline, qqplot

  • Gérer les paramètres graphiques : par().
  • Sauvegarder un graphique : graphics.off(), pdf(), png() et dev.off().


Hist

Histogramme : distribution de l’âge de la mère des portées

# Histogramme : distribution de l'âge de la mère
(h_agedam <- hist(dfvaris_litter$agedam, freq = FALSE, 
               main = "Distribution de l'âge de la mère des portées de varis",
               xlab = "Age de la mère en années", ylab = "Densité"))
## $breaks
##  [1]  2  4  6  8 10 12 14 16 18 20 22 24 26 28 30
## 
## $counts
##  [1] 270 266 229 184 135 108  65  41  23  10   7   1   0   1
## 
## $density
##  [1] 0.1007462687 0.0992537313 0.0854477612 0.0686567164 0.0503731343
##  [6] 0.0402985075 0.0242537313 0.0152985075 0.0085820896 0.0037313433
## [11] 0.0026119403 0.0003731343 0.0000000000 0.0003731343
## 
## $mids
##  [1]  3  5  7  9 11 13 15 17 19 21 23 25 27 29
## 
## $xname
## [1] "dfvaris_litter$agedam"
## 
## $equidist
## [1] TRUE
## 
## attr(,"class")
## [1] "histogram"

# Ajout d'une courbe de densité
dens_agedam <- density(dfvaris_litter$agedam)
lines(dens_agedam)

# Ajout d'une ligne verticale : moyenne des âges
abline(v = mean(dfvaris_litter$agedam), col = "red")

# Coloration de la densité pour les valeurs inférieures au 1er quartile
qrtle1 <- summary(dfvaris_litter$agedam)["1st Qu."]
polygon(c(0, dens_agedam$x[dens_agedam$x <= qrtle1]), 
        c(dens_agedam$y[dens_agedam$x <= qrtle1], 0), 
        col = rgb(1, 0, 0, alpha = 0.3))


A VOUS ! (avec des commandes R)

  • 3.2.A - Complétez ce graphique en colorant l’aire sous la courbe de densité pour les valeurs supérieures au 3ème quartile.


Hist

Histogramme : distribution de l’âge de la mère et du père des portées de chacune des deux espèces

par(mfrow = c(2, 2))

dfagedam_vr <- dfvaris_litter$agedam[dfvaris_litter$species == "Vrubra"]
hist(dfagedam_vr, freq = FALSE, main = "Distribution de l'âge de la\nmère des portées de V. Rubra", xlab = "Age de la mère", ylab = "Densité", col = "#69b3a2")
lines(density(dfagedam_vr))

dfagedam_vv <- dfvaris_litter$agedam[dfvaris_litter$species == "Vvariegata"]
hist(dfagedam_vv, freq = FALSE, main = "Distribution de l'âge de la\nmère des portées de V. Variegata", xlab = "Age de la mère", ylab = "", col = "#404080")
lines(density(dfagedam_vv))

dfagesire_vr <- dfvaris_litter$agesire[dfvaris_litter$species == "Vrubra"]
hist(dfagesire_vr, freq = FALSE, main = "Distribution de l'âge du\npère des portées de V. Rubra", xlab = "Age du père", ylab = "Densité", col = "#69b3a2")
lines(density(dfagesire_vr))


A VOUS ! (avec des commandes R)

  • 3.2.B - Sur le modèle de ces 3 sous-graphiques, complétez ce graphique en construisant un 4ème sous-graphique représentant la distribution de l’âge des pères des portées de l’espèce V. Variegata.


Boxplot

Boxplot : distribution de l’âge de la mère et du père des portées de chacune des deux espèces

summary(dfvaris_litter$agedam)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   2.000   5.000   8.000   8.515  11.000  30.000

bxpt_agedam <- boxplot(dfvaris_litter$agedam ~ dfvaris_litter$species, xlab = "", ylab = "Age de la mère", col = c("#69b3a2", "#404080"))

bxpt_agedam
## $stats
##      [,1] [,2]
## [1,]    2    2
## [2,]    5    5
## [3,]    8    8
## [4,]   12   11
## [5,]   21   20
## 
## $n
## [1] 378 962
## 
## $conf
##          [,1]     [,2]
## [1,] 7.431135 7.694353
## [2,] 8.568865 8.305647
## 
## $out
##  [1] 23 30 22 22 22 23 23 21 21 21 23 22 21 23 24 26 21 23
## 
## $group
##  [1] 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## 
## $names
## [1] "Vrubra"     "Vvariegata"


A VOUS ! (avec des commandes R)

  • 3.2.C - Sur le modèle de ce graphique, construisez un boxplot représentant la distribution de l’âge des pères des portées de chacune des deux espèces.


Boxplot

Boxplot : distribution de la taille de portée pour chaque espèce

bxpt_LSbirth <- boxplot(dfvaris_litter$littersizebirth ~ dfvaris_litter$species, xlab = "", ylab = "Taille de la portée", col = c("#69b3a2", "#404080"))

bxpt_LSbirth
## $stats
##      [,1] [,2]
## [1,]    1    1
## [2,]    1    1
## [3,]    2    2
## [4,]    3    2
## [5,]    5    3
## 
## $n
## [1] 378 962
## 
## $conf
##          [,1]     [,2]
## [1,] 1.837467 1.949059
## [2,] 2.162533 2.050941
## 
## $out
##  [1] 5 4 4 4 4 4 4 4 4 4 5 4 5 4 5 4 4 4 4 4 5 6 4 4 4 4 5 4 4 4 4 4 4 4 4
## [36] 4 6 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 4
## 
## $group
##  [1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [36] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## 
## $names
## [1] "Vrubra"     "Vvariegata"


3.3 Des visualisations performantes

Dans R, la visualisation graphique des données :

  • géré historiquement par le package graphics (R Core Team 2018a)
  • réinventé par des packages comme grid (Murrell 2011, @R-base), lattice (Sarkar 2008), ggplot2 (Wickham 2016)

ggplot2

  • Les graphiques sont des objets stockables et modifiables.
  • Les graphiques sont construits à partir d’un objet formula qui exprime la dépendance entre les variables à représenter.
  • Les objets graphiques sont esthétiquement plus modernes, plus facilement modifiables, plus facile à combiner.
  • De plus en plus utilisé, dans tous les domaines.
  • Propose un grand nombre de fonctionnalités.
  • En contrepartie, la grammaire liée à ces graphiques se revèle plus complexe à appréhender pour construire des graphiques élaborés.



Hist

Histogramme : distribution de l’âge de la mère des portées

library(ggplot2)
df_dens_agedam <- as.data.frame(cbind(x = dens_agedam$x, y = dens_agedam$y))

(gg_hist_agedam <- ggplot(data = dfvaris_litter, aes(x = agedam)) + 
  ggtitle("Distribution de l'âge de la mère des portées de varis") + 
  xlab("Age de la mère en années") + ylab("Densité") +
  geom_histogram(alpha = 0.4, breaks = h_agedam$breaks, aes(y = ..density..), colour = "black") +
  geom_vline(xintercept = mean(dfvaris_litter$agedam), colour = "red") +
  geom_density(alpha = 0.2) +
  geom_ribbon(data = subset(df_dens_agedam, x <= qrtle1), aes(x = x, ymax = y), ymin = 0, fill = "red", alpha = 0.3) +
  geom_ribbon(data = subset(df_dens_agedam, x >= qrtle3), aes(x = x, ymax = y), ymin = 0, fill = "red", alpha = 0.3)
)


Hist

Histogramme : distribution de l’âge de la mère et du père des portées de chacune des deux espèces

library(gridExtra)
gg_hist_age_spe <- list()

gg_hist_age_spe[[1]] <- ggplot(data = dfvaris_litter, aes(x = agedam)) + 
    ggtitle("") + xlab("Age de la mère en années") + ylab("Densité") +
    geom_histogram(alpha = 0.4, aes(y = ..density.., fill = species), bins = 15, color = "grey30") +
    geom_density(alpha = 0.2) +
    scale_fill_manual(values = c("#69b3a2", "#404080")) +
    facet_wrap(~ species) +
    theme(legend.position = "none")

gg_hist_age_spe[[2]] <- ggplot(data = dfvaris_litter, aes(x = agesire)) + 
    ggtitle("") + xlab("Age du père en années") + ylab("Densité") +
    geom_histogram(alpha = 0.4, aes(y = ..density.., fill = species), bins = 10, color = "grey30") +
    geom_density(alpha = 0.2) +
    scale_fill_manual(values = c("#69b3a2", "#404080")) +
    facet_wrap(~ species) +
    theme(legend.position = "none")

do.call(grid.arrange, c(gg_hist_age_spe, nrow = 2))


Boxplot
library(gridExtra)
gg_bxplt_age_spe <- list()

gg_bxplt_age_spe[[1]] <- ggplot(data = dfvaris_litter, aes(x = species, y = agedam)) +
  geom_boxplot(aes(fill = factor(species)), fill = c("#69b3a2", "#404080")) + guides(fill=FALSE) +
  xlab("") + ylab("Age de la mère")
gg_bxplt_age_spe[[2]] <- ggplot(data=dfvaris_litter, aes(x = species, y = agesire)) + 
  geom_boxplot(aes(fill = factor(species)), fill = c("#69b3a2", "#404080")) + guides(fill=FALSE) +
    xlab("") + ylab("Age du père")

do.call(grid.arrange, c(gg_bxplt_age_spe, ncol = 2))


Boxplot
# boxplot : taille de portée par espèce
(gg_bxplt_ls_spe <- ggplot(dfvaris_litter, aes(x = species, y = littersizebirth)) + 
  xlab("") + ylab("Taille de la portée") +
  geom_boxplot(fill = c("#69b3a2", "#404080")))

# violin plot
(gg_violin_ls_spe <- ggplot(dfvaris_litter, aes(x = species, y = littersizebirth, fill = species)) + 
  xlab("") + ylab("Taille de la portée") +
  geom_violin(alpha = 0.2) +
  scale_fill_manual(values = c("#69b3a2", "#404080")))

# boxplot avec les points
(gg_jitter_ls_spe <- ggplot(dfvaris_litter, aes(x = species, y = littersizebirth)) + 
  xlab("") + ylab("Taille de la portée") +
  geom_boxplot(fill = c("#69b3a2", "#404080"), alpha = 0.2) + 
  geom_jitter(color = "black", size = 0.4, alpha = 0.9))


A VOUS ! (avec des commandes R)

  • 3.3.A - A l’aide du package ggplot2, reproduisez la figure que vous avez construite à la question 3.1.A, inspirée de la Figure S1 en annexe de l’article de Tidière et al. (2018).




D’autres outils graphiques à explorer

  • Données spatiales et cartographie : rgdal, sp, rgeos, cartography
  • Séries temporelles : dygraphs (basé sur la bibliothèque JavaScript dygraphs)
  • Phylogénies : ape, ggtree, phylogram
  • Graphes (network) : igraph, ggnet2
  • JavaScript dans R : htmlwidgets, rAmCharts (basé sur la bibliothèque JavaScript amcharts.js)

3.4 Des visualisations interactives

  • Rendre des représentations attractives, originales et faciles à inclure dans des pages web.
  • Déclencher l’intérêt d’un public non-spécialiste.
  • Augmenter le niveau d’information contenu dans les graphiques pour mieux communiquer.
  • Utiliser des packages R qui s’appuient sur des bibliothèques JavaScript.
  • Le développeur ou la développeuse n’a pas besoin d’apprendre un autre langage que R.

Des packages dédiés

  • Graphiques généraux : plotly (Sievert 2018)
  • Données spatiales et cartographie : leaflet (Cheng, Karambelkar, and Xie 2018)
  • Graphes (network) : networkD3 (Allaire et al. 2017), visNetwork (Almende B.V., Thieurmel, and Robert 2019)
  • 3D : threejs (Lewis 2017), rgl (Adler, Murdoch, and others 2019)
  • Tables de données : DT (Xie, Cheng, and Tan 2019)
  • Heatmaps : d3heatmap (Cheng and Galili 2018)

Fonctionnalités automatiquement gérées

  • zoom
  • affichage d’informations statistiques
  • affichage des coordonnées des points
  • apparition et disparition de points
  • export du graphique


Xyplot

Relation entre l’âge du père et l’âge de la mère chez les varis

plotly::ggplotly(gg_agedamsire)


Hist

Histogramme : distribution de l’âge de la mère des portées

plotly::ggplotly(gg_hist_agedam)


Boxplot

Boxplot : taille de portée par espèce

plotly::ggplotly(gg_bxplt_ls_spe)

4 Des applications web avec shiny

4.1 Introduction

4.1.1 C’est quoi shiny ?

  • shiny (Chang et al. 2017) est un package R.
  • Une application shiny est constitué de deux éléments :
    • une partie qui gère l’interface avec l’utilisateur.trice (User Interface) et définit la mise en page et l’apparence de l’application,
    • une partie qui gère les interactions avec le serveur et contient les instructions dont le serveur à besoin pour contruire l’application.
  • Le code de l’application shiny peut être contenu dans un seul fichier appelé app.R ou dans deux fichiers séparés appelés ui.R et server.R. Cette dernière solution est à priviliégier pour plus de clarté dans le code.
  • Une application est lancée par la commande runApp() ou par le bouton ‘Run App’ de RStudio.
  • La totalité d’une application shiny peut être codée en R, pas besoin de connaître d’autres langages.
  • Il est cependant possible d’intégrer du css, du html, du JavaScript, …
  • De nombreux packages ont été développés autour de shiny : shinydashboard (Chang and Borges Ribeiro 2018), shinyWidgets (Perrier, Meyer, and Granjon 2019), shinycssloaders (Sali 2017), shinythemes (Chang 2018), shinyBS (Bailey 2015), shinyjs (Attali 2018), …

Pour que l’application puisse être déployée, elle doit être contenue dans un répertoire définit comme suit :

  • les fichiers “ui.R” et “server.R” à la racine
  • des sous-dossiers contenants des données, des scripts, …
  • un dossier “www” contenant des éléments qui ne sont pas nécessaires aux calculs R (images, logos, feuilles de styles, …)
  • le nom du répertoire détermine le nom de l’application
  • un fichier “global.R” peut être ajouté à la racine : il sera exécuté au lancement de l’application, avant tout autre chose, et une seule fois par session.

4.1.2 Côté interface

4.1.2.1 Les inputs

Les inputs sont gérés via des widgets (window gadgets).

Quelques widgets standards :


Les widgets sont :

  • définis, a minima, par un nom (non visible dans l’interface mais utilisé pour accéder à la valeur du widget) et un label (affiché dans l’interface)
  • des éléments dynamiques
  • en interaction avec l’utilisateur.trice
  • associés à une valeur renvoyée au serveur
  • créés par des fonction prédéfinies



4.1.2.2 Les outputs

4.1.2.3 La mise en page et l’apparence de l’application

Les panels

  • pour regrouper plusieurs éléments de l’interface (texte, image, widget) dans un même ensemble caractérisé par un style défini
  • wellPanel(), sidebarPanel(), mainPanel(), conditionalPanel(), headerPanel(), fixedPanel(), tabPanel(), titlePanel(), …

Les éléments réactifs

  • par essence les outputs sont réactifs
  • la fonction reactive() permet de moduler la réactivité des éléments ; elle est utile notament quand certains morceaux de codes sont utilisés par plusieurs outputs.
  • les fonctions eventReactive(), observe() et observeEvent() permettent de décelncher ou retarder une réaction
  • la fonction isolate() bloque une réaction

Personnalisation

  • fonctions wrapper pour intégrer des éléments de mise en forme
  • possibilité d’utiliser plus de tag HTML, disponibles dans la liste données par names(tags)
  • associer une feuille de style à l’application, stockée dans le répertoire “www”

4.1.3 Côté serveur

A chaque fonction *Output() (côté ui) correspond une fonction render*() (côté server). Se tromper de fonction associée engendrera un affichage vide (pas forcément une erreur).

4.1.4 Exemples d’applications shiny

Ex0
# liste des exemples d'applis shiny disponibles dans le package 'shiny'
shiny::runExample()
## Valid examples are "01_hello", "02_text", "03_reactivity", "04_mpg", "05_sliders", "06_tabsets", "07_widgets", "08_html", "09_upload", "10_download", "11_timer"
Ex1
shinyAppDir(
  system.file("examples/04_mpg", package="shiny"),
  options = list(width = "100%", height = 700)
)


Ex2
shinyApp(

  ui = fluidPage(
    selectInput("region", "Region:",
                choices = colnames(WorldPhones)),
    plotOutput("phonePlot")
  ),

  server = function(input, output) {
    output$phonePlot = renderPlot({
      barplot(WorldPhones[,input$region]*1000,
              ylab = "Number of Telephones", xlab = "Year")
    })
  },

  options = list(height = 500)
)




4.2 Se familiariser et se perfectionner avec shiny

4.2.1 Lancer une application à partir d’un code existant


A VOUS ! (avec des commandes R)

  • 4.2.A - Créez une application (qui s’affiche et réagit comme attendu) à partir des codes ci-dessous. Cette première application s’appuie sur le jeu de données doubs d’ade4 vu dans la section 2.1.
# ui.R
shinyUI(fluidPage(
    
    # Titre de l'application
    titlePanel("Exploration du jeu de données doubs d'ade4"),
    
    # Menu déroulant pour choisir une espèce
    # La liste des espèces est définie par les colonnes de doubs$fish
    selectInput("espece", "Sélectionnez une espèce:",
                choices = colnames(doubs$fish)),
    
    # Graphique représentant l'abondance de l'espèce sélectionné à chaque position géographique (doubs$xy)
    plotOutput("abondancePlot")
))
# server.R
library(shiny)
library(ade4)

shinyServer(function(input, output) {

    output$abondancePlot <- renderPlot({

        data(doubs)
        df_espece <- doubs$fish[[input$espece]]
        plot(doubs$xy$x, doubs$xy$y, 
             cex = ifelse(df_espece == 0, 1, df_espece),
             pch = ifelse(df_espece == 0, 4, 19))
    })
})


4.2.2 Créer une application simple

A VOUS ! (avec des commandes R)

  • 4.2.B - Dans le but de rendre disponible vos analyses sur le jeu de données dfvaris_litter, créez une application qui permettra d’afficher la distribution (histogramme et courbe de densité) de l’âge des parents pour les espèces de varis (voir les graphiques dans les deuxièmes onglets des sections 3.2 et 3.3). Cette application contiendra :
    • un titre
    • un paragraphe explicatif sur le jeu de données
    • un objet interactif qui permet de sélectionner une des deux espèces ou les deux
    • un objet interactif qui permet de sélectionner le père, la mère ou les deux
    • une zone graphique contenant le ou les graphiques (selon les valeurs des deux objets interactifs précédents) de la distribution de l’âge des parents des portées de varis.

4.2.3 Manipuler des graphiques statiques et interactifs

A VOUS ! (avec des commandes R)

  • 4.2.C - Dans le but de rendre disponible vos analyses sur le jeu de données dfvaris_litter, créez une application qui affiche le même graphique (par exemple, le boxplot représentant la distribution de la taille des portées de varis dans les 2 espèces, voir dernier onglet des sections 3.2 et 3.3) sous 3 formes différentes : le 1er généré à partir du package graphics, le 2ème généré à partir du package ggplot2 et le 3ème généré à partir des packages ggplot2 et plotly.

4.2.4 Explorer un graphique dans une application

A VOUS ! (avec des commandes R)

  • 4.2.D - Dans le but de rendre disponible vos analyses sur le jeu de données dfvaris_litter, créez une application qui permettra d’afficher la distribution (histogramme et courbe de densité) de l’âge des parents pour les espèces de varis (voir les graphiques dans les deuxièmes onglets des sections 3.2 et 3.3). Cette application contiendra :
    • un titre
    • un paragraphe explicatif sur le jeu de données
    • un objet interactif qui permet de sélectionner une des deux espèces ou les deux
    • un objet interactif qui permet de sélectionner le père, la mère ou les deux
    • une zone graphique contenant le ou les graphiques (selon les valeurs des deux objets interactifs précédents) de la distribution de l’âge des parents des portées de varis.
  • single checkbox pour afficher ou pas la légende
  • slider pour faire varier la grosseur des points
  • select box pour sélectionner une couleur
  • select box pour choisir la variable représentée (espèce)
  • bouton pour télécharger le graphique

Annexes

Données Varis

Les données que nous allons utiliser dans ce cours sont issues du Studbook Internationnal des lémuriens (Whipple 2014 , 2016). Ce Studbook répertorie la majorité des lémuriens de deux espèces (Varecia rubra et Varecia variegata) vivant en captivité (322 zoos à travers le monde) entre 1959 et 2015. Les deux espèces de lémuriens suivies sont deux espèces très proches. On pourra noter que l’âge de sevrage des petits (weaning) est atteint 146 jours après leur naissance (0.4 an), que la maturité sexuelle des individus est atteinte à l’âge de 1.16 an et que 1 à 7 petits peuvent constituer une portée (litter). Le jeu de données complet du Studbook contient 1954 V. rubra et 4169 V. variegata. La qualité de ce jeu de données est attribuable à la rigueur des personnels des zoos, qui peuvent réaliser, grâce aux conditions de captivité, un suivi minutieux des populations.

A partir de ce jeu de données conséquent, Tidière et al. (2018) ont étudié dans leur article l’effet de l’âge des parents et de leur différence d’âge sur (1) la taille des portées et (2) la survie des descendants. Cet article apporte de nouvelles connaissances sur ces deux espèces de lémuriens et donne donc des pistes pour améliorer leur conservation et la gestion de leur population.

Dans le cadre de ce cours, seule une partie des données de Tidière et al. (2018) va être analysée. Ce jeu de données se nomme dfvaris_litter, compte 1109 portées étudiés sur 13 variables :

  • species : l’espèce (V. rubra ou V. variegata)
  • yearbirth : l’année de naissance de la portée
  • littersizebirth : la taille de la portée
  • littersizeweaning : le nombre d’individus de la portée qui ont atteint l’âge de sevrage
  • sexratiobirth : le sex-ratio de la portée à la naissance
  • sexratioweaning : le sex-ratio de la portée à l’âge de sevrage
  • survlitter48h : le taux de survie de la portée à 48h
  • survlitterweaning : le taux de survie de la portée à l’âge du sevrage
  • survlittersexmat : le taux de survie de la portée à l’âge de la maturité sexuelle
  • agedam : l’âge de la mère à la naissance de la portée
  • agemaxdam : l’âge maximal atteint par la mère
  • agesire : l’âge du père à la naissance de la portée
  • agemaxsire : l’âge maximal atteint par le père



Adler, Daniel, Christian Gläser, Oleg Nenadic, Jens Oehlschlägel, and Walter Zucchini. 2018. Ff: Memory-Efficient Storage of Large Data on Disk and Fast Access Functions. https://CRAN.R-project.org/package=ff.

Adler, Daniel, Duncan Murdoch, and others. 2019. Rgl: 3D Visualization Using Opengl. https://CRAN.R-project.org/package=rgl.

Allaire, J.J., Christopher Gandrud, Kenton Russell, and CJ Yetman. 2017. NetworkD3: D3 Javascript Network Graphs from R. https://CRAN.R-project.org/package=networkD3.

Almende B.V., Benoit Thieurmel, and Titouan Robert. 2019. VisNetwork: Network Visualization Using ’Vis.js’ Library. https://CRAN.R-project.org/package=visNetwork.

Attali, Dean. 2018. Shinyjs: Easily Improve the User Experience of Your Shiny Apps in Seconds. https://CRAN.R-project.org/package=shinyjs.

Bache, Stefan Milton, and Hadley Wickham. 2014. magrittr: A Forward-Pipe Operator for R. https://CRAN.R-project.org/package=magrittr.

Bailey, Eric. 2015. ShinyBS: Twitter Bootstrap Components for Shiny. https://CRAN.R-project.org/package=shinyBS.

Chambers, John M. 2008. Software for Data Analysis, Programming with R. Edited by Springer. https://doi.org/10.1007/978-0-387-75936-4.

Chang, Winston. 2018. Shinythemes: Themes for Shiny. https://CRAN.R-project.org/package=shinythemes.

Chang, Winston, and Barbara Borges Ribeiro. 2018. Shinydashboard: Create Dashboards with ’Shiny’. https://CRAN.R-project.org/package=shinydashboard.

Chang, Winston, Joe Cheng, JJ Allaire, Yihui Xie, and Jonathan McPherson. 2017. shiny: Web Application Framework for R. https://CRAN.R-project.org/package=shiny.

Charif, D., and J.R. Lobry. 2007. “SeqinR 1.0-2: A Contributed Package to the R Project for Statistical Computing Devoted to Biological Sequences Retrieval and Analysis.” In Structural Approaches to Sequence Evolution: Molecules, Networks, Populations, edited by U. Bastolla, M. Porto, H.E. Roman, and M. Vendruscolo, 207–32. Biological and Medical Physics, Biomedical Engineering. New York: Springer Verlag.

Cheng, Joe, and Tal Galili. 2018. D3heatmap: Interactive Heat Maps Using ’Htmlwidgets’ and ’D3.js’. https://CRAN.R-project.org/package=d3heatmap.

Cheng, Joe, Bhaskar Karambelkar, and Yihui Xie. 2018. Leaflet: Create Interactive Web Maps with the Javascript ’Leaflet’ Library. https://CRAN.R-project.org/package=leaflet.

Couture-Beil, Alex. 2018. Rjson: JSON for R. https://CRAN.R-project.org/package=rjson.

Crawley, Michael J. 2013. The R Book. Edited by Wiley. https://doi.org/10.1002/9781118448908.

Gagolewski, Marek. 2017. R package stringi: Character string processing facilities. http://www.gagolewski.com/software/stringi/.

GmbH, Mirai Solutions, Martin Studer, The Apache Software Foundation, and Graph Builder. 2018. XLConnect: Excel Connector for R. https://CRAN.R-project.org/package=XLConnect.

Kane, Michael J., John Emerson, and Stephen Weston. 2013. “Scalable Strategies for Computing with Massive Data.” Journal of Statistical Software 55 (14): 1–19. http://www.jstatsoft.org/v55/i14/.

Lang, Duncan Temple, and the CRAN Team. 2019. XML: Tools for Parsing and Generating Xml Within R and S-Plus. https://CRAN.R-project.org/package=XML.

Lewis, B. W. 2017. Threejs: Interactive 3D Scatter Plots, Networks and Globes. https://CRAN.R-project.org/package=threejs.

LLC, MultiMedia. 1999. “MS Windows NT Kernel Description.” 1999. https://gist.github.com/daroczig/3cf06d6db4be2bbe3368.

Murrell, Paul. 2011. R Graphics. Edited by Chapman & Hall. https://www.stat.auckland.ac.nz/~paul/RG2e/.

Neuwirth, Erich. 2014. RColorBrewer: ColorBrewer Palettes. https://CRAN.R-project.org/package=RColorBrewer.

Perrier, Victor, Fanny Meyer, and David Granjon. 2019. ShinyWidgets: Custom Inputs Widgets for Shiny. https://CRAN.R-project.org/package=shinyWidgets.

R Core Team. 2017. foreign: Read Data Stored by Minitab, S, SAS, SPSS, Stata, Systat, Weka, dBase, ... https://CRAN.R-project.org/package=foreign.

———. 2018a. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.

———. 2018b. Writing R Extensions. https://cran.r-project.org/doc/manuals/r-release/R-exts.html.

Sali, Andras. 2017. Shinycssloaders: Add Css Loading Animations to ’Shiny’ Outputs. https://CRAN.R-project.org/package=shinycssloaders.

Sarkar, Deepayan. 2008. Lattice, Multivariate Data Visualisation with R. Edited by Springer. https://doi.org/10.1007/978-0-387-75969-2.

Sievert, Carson. 2018. Plotly for R. https://plotly-r.com.

Tidière, Morgane, Xavier Thevenot, Adamantia Deligiannopoulou, Guillaume Douay, Mylisa Whipple, Aurélie Siberchicot, Jean-Michel Gaillard, and Jean-François Lemaître. 2018. “Maternal Reproductive Senescence Shapes the Fitness Consequences of the Parental Age Difference in Ruffed Lemurs.” Proceedings of the Royal Society B: Biological Sciences 285 (1886). https://doi.org/10.1098/rspb.2018.1479.

Whipple, M. 2014. “International Studbook for Ruffed Lemurs.” Saint Louis, Missouri: Saint Louis Zoo.

———. 2016. “International and North American Regional Studbooks for Ruffed Lemurs.” Saint Louis, Missouri: Saint Louis Zoo.

Wickham, Hadley. 2011. “The Split-Apply-Combine Strategy for Data Analysis.” Journal of Statistical Software 40 (1): 1–29. http://www.jstatsoft.org/v40/i01/.

———. 2015a. Advanced R. Edited by Chapman & Hall. http://adv-r.had.co.nz/.

———. 2015b. R Packages. Edited by O’Reilly. http://r-pkgs.had.co.nz/.

———. 2016. ggplot2, Elegant Graphics for Data Analysis. Edited by Springer. http://ggplot2.org/.

———. 2018. stringr: Simple, Consistent Wrappers for Common String Operations. https://CRAN.R-project.org/package=stringr.

Wickham, Hadley, and Jennifer Bryan. 2019. Readxl: Read Excel Files. https://CRAN.R-project.org/package=readxl.

Wickham, Hadley, Romain Francois, Lionel Henry, and Kirill Müller. 2017. Dplyr: A Grammar of Data Manipulation. https://CRAN.R-project.org/package=dplyr.

Wickham, Hadley, and Lionel Henry. 2018. tidyr: Easily Tidy Data with ’spread()’ and ’gather()’ Functions. https://CRAN.R-project.org/package=tidyr.

Wickham, Hadley, Jim Hester, and Romain Francois. 2018. Readr: Read Rectangular Text Data. https://CRAN.R-project.org/package=readr.

Xie, Yihui, Joe Cheng, and Xianying Tan. 2019. DT: A Wrapper of the Javascript Library ’Datatables’. https://CRAN.R-project.org/package=DT.